import { Injectable } from '@angular/core';

export class Req {
  public headers: any
  public body: string

  constructor(public url: string, public type: string, public data?: any) { }
}

export class Res {
  constructor(public status: number, public error: string, public msg: string,
              public data: any) { }
}

@Injectable()
export class AjaxService {
  public static APIROOT = "/api/bigdata/pm/dev"

  public static sleep(time: number): Promise<number> {
    return new Promise(resolve => setTimeout(resolve, time))
  }

  public static request(req: Req): Promise<Res> {
    var res: Res = new Res(0, "FAIL", null, null)
    return new Promise<Res>(resolve => {
      var qry = () => {
        if (AjaxService.going)
          AjaxService.sleep(200).then(() => { qry() })
        else {
          AjaxService.going = true
          AjaxService.go(req).then(res_c => {
            res.status = res_c.status
            res.error = res_c.error
            res.msg = res_c.msg
            res.data = res_c.data
            AjaxService.going = false
            resolve()
          })
        }
      }; qry()
    }).then(() => res)
  }

  private static going: boolean = false

  private static go(req: Req): Promise<Res> {
    var res: Res = new Res(206, null, null, null)

    return new Promise<Res>(resolve => {
      var httpRequest = new XMLHttpRequest()
      httpRequest.onreadystatechange = () => {
        if (httpRequest.readyState === XMLHttpRequest.DONE) {
          res.status = httpRequest.status
          try {
            var res_j = JSON.parse(httpRequest.responseText)
            res.error = res_j.error
            res.msg = res_j.msg
            res.data = res_j.data
          } catch(e) {
            res.error = e.name || e
            res.msg = e.message
          }

          resolve()
        }
      }
      var serialize = (obj: any, prefix?: string) => {
        if (!obj) return
        var str:Array<string> = [ ]
        var objIsArr = Array.isArray(obj)
        Object.keys(obj).map((p: string) => {
          var k = prefix ? prefix + "[" + (objIsArr ? ""  : p) + "]" : p, v = obj[p]
          str.push((v !== null && typeof v === "object") ?
                  serialize(v, k) : encodeURIComponent(k) + "=" + (
                    v === null || typeof(v) === "undefined" ? "" :
                      encodeURIComponent(v)))
        })
        return str.join("&")
      }
      var qry: string = serialize(req.data)
      if (qry) {
        if ("GET" == req.type.toUpperCase())
          req.url += "?" + qry
        else
          req.body = qry
      }
      httpRequest.open(req.type, req.url)
      if ([ "POST", "PUT" ].indexOf(req.type.toUpperCase()) != -1)
        httpRequest.setRequestHeader('Content-Type',
                                     'application/x-www-form-urlencoded')
      if (req.headers)
        Object.keys(req.headers).map(function(key) {
          httpRequest.setRequestHeader(key, req.headers[key]); })
      httpRequest.send(req.body)
    }).then(() => res)
  }
}
